/**
 * Created by Forcs on 16/4/14.
 */

var model = require('../db/Model');
var co = require('co');
var utils = require('../utils/Utils');

var Manager = function () {
  this._cached = {};
  var self = this;

  self._cacheProductDoc = function (productCode, doc) {
    self._cached[productCode] = doc;
  };

  self._getProductDocFromCached = function (productCode) {
    if (self._cached === undefined || !self._cached[productCode]) {
      return null;
    }
    return self._cached[productCode];
  };
};

Manager.prototype.addProduct = function (doc, func) {
  var self = this;
  return new Promise(function (resolve, reject) {
    co(function * () {
      var result = yield self.insert(doc, { notifiedEvent: 'add.product'});
      if (utils.isFunction(func)) {
        func.call(self, undefined, result);
      }
      resolve(result);
    }).catch(function (err) {
      if (utils.isFunction(func)) {
        func.call(self, err);
      }
      reject(err);
    });
  });
};

Manager.prototype.addCategory = function (productCode, doc, func) {
  var self = this;
  return new Promise(function (resolve, reject) {
    co(function * () {
      // 先从缓存获取,如果缓存没有,那么就从数据库中获取,然后缓存
      var productDoc = self._getProductDocFromCached(productCode);
      if (!productDoc) {
        productDoc = yield self.$model.findOne({ code: productCode }).exec();
        self._cacheProductDoc(productCode, productDoc);
      }
      // 查不到对于的产品文档,那么就直接返回
      if (!productDoc) {
        throw 'code ' + productCode + ' 的产品信息不存在';
      }
      var added = productDoc.categories.addToSet(doc);
      var result = yield productDoc.save();
      result.added = added;
      result.addedCount = added.length;
      result.product = productCode;
      result.biz = productDoc.biz;
      self.notify('add.category', result);
      if (utils.isFunction(func)) {
        func.call(self, undefined, result);
      }
      resolve(result);
    }).catch(function (err) {
      if (utils.isFunction(func)) {
        func.call(self, err);
      }
      reject(err);
    });
  });
};

Manager.prototype.addContent = function (productCode, categoryCode, doc, func) {
  var self = this;
  return new Promise(function (resolve, reject) {
    co(function * () {
      var productDoc = self._getProductDocFromCached(productCode);
      if (!productDoc) {
        productDoc = yield self.$model.findOne({ code: productCode }).exec();
        self._cacheProductDoc(productCode, productDoc);
      }
      if (!productDoc) {
        throw 'code ' + productCode + ' 的产品信息不存在';
      }
      var categoryDoc = undefined;
      var categories = productDoc.categories;
      if (categories) {
        var i = categories.length;
        while (i--) {
          if (categories[i].code === categoryCode) {
            categoryDoc = categories[i];
            break;
          }
        }
      }
      if (!categoryDoc) {
        throw 'code ' + categoryCode + ' 的栏目信息不存在';
      }
      var added = categoryDoc.contents.addToSet(doc);
      var result = yield productDoc.save();
      result.added = added;
      result.addedCount = added.length;
      result.product = productCode;
      result.category = categoryCode;
      result.biz = productDoc.biz;
      self.notify('add.content', result);
      if (utils.isFunction(func)) {
        func.call(self, undefined, result);
      }
      resolve(result);
    }).catch(function (err) {
      if (utils.isFunction(func)) {
        func.call(self, err);
      }
      reject(err);
    });
  });
};

Manager.prototype.allWithBiz = function (biz, projection, options, func) {
  var self = this;
  return new Promise(function (resolve, reject) {
    co(function * () {
      var querySet = undefined;
      if (self._cached[biz]) {
        querySet = self._cached[biz];
      }
      if (!querySet) {
        querySet = self.find({ biz: biz }, projection, options, func);
        self._cached[biz] = querySet;
      }
      resolve(self._cached[biz]);
    }).catch(function (err) {
      reject(err);
    })
  });
};

module.exports = model.create('Products', {
  code: String,
  name: String,
  token: String,
  biz: String,
  categories: [
    {
      code: String,
      name: String,
      contents: [
        {
          code: String,
          name: String
        }
      ]
    }
  ]
}, Manager);